//
// Copyright (c) 2009 Tridium, Inc.
// Licensed under the Academic Free License version 3.0
//
// History:
//   24 Feb 09  Dan Giorgis  Creation
//

#include "sedona.h"

#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>

#include <unistd.h>

#include "math.h"


// assumed that we have 12 digital output channel for use.

#define		AoChannel		12

static float 	out_c=0;
static float 	out_hook_c=0;   // for timing computation
static float	raw_c=0;

static int 		channel_c=0;
static bool 	reversePolarity_c=0;		// Voltage, 0 to 5v
static int 		minOnTime_c=0;
static int		minOffTime_c=0;
static int		interDelay_c=0;

static float	scaleLow_c=0;
static float	scaleHigh_c=100;

static bool	clampingHighEnable_c=0;
static float	clampingHigh_c=100;
static bool	clampingLowEnable_c=0;
static float	clampingLow_c=100;

static int		outputType_c=0;
static bool	reverseOutput_c=0;
static bool	squareRoot_c=0;

static float	max_c[AoChannel];
static float	min_c[AoChannel];


// from the class of 'DigitalOutputStatus'

static int 		onCounter_c[12];
static int		offCounter_c[12];
static int		onTimer_c[12];
static int		offTimer_c[12];

// proririty index - -1: null (inactive)

static float	in1_c=-1;
static float	in2_c=-1;
static float	in3_c=-1;
static float	in4_c=-1;
static float	in5_c=-1;
static float	in6_c=-1;
static float	in7_c=-1;
static float	in8_c=-1;
static float	in9_c=-1;
static float	in10_c=-1;
static float	in11_c=-1;
static float	in12_c=-1;
static float	in13_c=-1;
static float	in14_c=-1;
static float	in15_c=-1;
static float	in16_c=-1;

static float 	relinquishDefault_c=0;

static float channel_to_out[12];
static float channel_to_pri[12][16] = {-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1,
	-1, -1, -1,-1,-1,-1,-1,-1,-1, -1, -1,-1,-1,-1,-1,-1};





////////////////////////////////////////////////////////////////
// Native Methods
////////////////////////////////////////////////////////////////

//  Temparature (0 - 100 oC) <=> Voltage (0 - 3.3 v)
Cell vonplusBasic_aop_set(SedonaVM* vm, Cell* params)
{
	
       channel_c = params[0].ival;    

	 if (channel_c==0) 
	 	return zeroCell;
	 
	int pri_in_idx= params[1].ival;    
	float in= params[2].ival;  

	//printf(" aop set for channel %d, pri %d, in %d \n", channel_c, pri_in_idx, in);
	

	if (pri_in_idx==1) // only for the current and voltages (0, 1, 2, 3)
		in1_c= in;
	else if (pri_in_idx==2) 
		in2_c= in;
	else if (pri_in_idx==3) 
		in3_c= in;
	else if (pri_in_idx==4) 
		in4_c= in;
	else if (pri_in_idx==5) 
		in5_c= in;
	else if (pri_in_idx==6) 
		in6_c= in;
	else if (pri_in_idx==7) 
		in7_c= in;
	else if (pri_in_idx==8) 
		in8_c= in;
	else if (pri_in_idx==9) 
		in9_c= in;
	else if (pri_in_idx==10) 
		in10_c= in;
	else if (pri_in_idx==11) 
		in11_c= in;
	else if (pri_in_idx==12) 
		in12_c= in;
	else if (pri_in_idx==13) 
		in13_c= in;
	else if (pri_in_idx==14) 
		in14_c= in;
	else if (pri_in_idx==15) 
		in15_c= in;
	else if (pri_in_idx==16) 
		in16_c= in;


	//printf(" aop set for channel    ^^^^^^^^^^^^^^^   %d \n", channel_c);
	channel_to_pri[channel_c-1][pri_in_idx-1] = in;

	if (in1_c==-1)
	{
	if (in2_c==-1)
	{
	if (in3_c==-1)
	{
	if (in4_c==-1)
	{
	if (in5_c==-1)
	{
	if (in6_c==-1)
	{
	if (in7_c==-1)
	{
	if (in8_c==-1)
	{
	if (in9_c==-1)
	{
	if (in10_c==-1)
	{
	if (in11_c==-1)
	{
	if (in12_c==-1)
	{
	if (in13_c==-1)
	{
	if (in14_c==-1)
	{
	if (in15_c==-1)
	{
	if (in16_c==-1)
	{	
		out_c=relinquishDefault_c;
		//printf(" set for ===========  fallback \n");
	}
	else
	{
			out_c=in16_c;
			//printf(" set for ===========  in16 \n");
		}
	}
	else
		{
			out_c=in15_c;
			//printf(" set for ===========  in15 \n");
		}
	}
	else
		{
			out_c=in14_c;
		}
	}
	else
		{
			out_c=in13_c;
		}
	}
	else
		{
			out_c=in12_c;
		}
	}
	else
		{
			out_c=in11_c;
		}
	}
	else
		{
			out_c=in10_c;
		}
	}
	else
		{
			out_c=in9_c;
		}
	}
	else
		{
			out_c=in8_c;
		}
	}
	else
		{
			out_c=in7_c;
		}
	}
	else
		{
			out_c=in6_c;
		}
	}
	else
		{
			out_c=in5_c;
		}
	}
	else
		{
			out_c=in4_c;
		}
	
	}
	else
		{
			out_c=in3_c;
		}
	}
	else
		{
			out_c=in2_c;
		}
	}
	else
	{
			out_c=in1_c;
	}

	out_hook_c = out_c;
	channel_to_out[channel_c-1]=out_c;

	//printf("aop set channel = %d \n", channel_c);
	
/*
	int fd;
	fd = open("/dev/leds0", 0);
	//printf("fd1=  %d\n", fd);
	if (fd < 0) {
		fd = open("/dev/leds", 0);
		//printf("fd2=  %d\n", fd);
	}
	if (fd < 0) {
		perror("open device leds");
		exit(1);
	}

	//printf("aop set out 3333 = %d \n", out_c);

	//printf("\n\n");
	
	ioctl(fd, out_c, channel_c);
	close(fd);
*/
	
  	 return zeroCell;

}

Cell vonplusBasic_aop_get(SedonaVM* vm, Cell* params)
{

	channel_c = params[0].ival;    

	//printf(" aop get channel %d\n", channel_c);
	
	  Cell result;

	  if (channel_c==0)
	  	result.fval = 0;
	  else
	 	result.fval = channel_to_out[channel_c-1]; 
	   
	  return result;

}



Cell vonplusBasic_aop_getRaw(SedonaVM* vm, Cell* params)
{

	channel_c = params[0].ival;    

	//printf(" aop get channel %d\n", channel_c);
	
	  Cell result;

	  if (channel_c==0)
	  	result.fval = 0;
	  else
	 	result.fval = channel_to_out[channel_c-1]; 
	   
	  return result;

	 
}


Cell vonplusBasic_aop_getStatus(SedonaVM* vm, Cell* params)
{
	printf("aop get status\n");
	channel_c = params[0].ival;    

	params[1].ival = 2; //onCounter_c[channel_c-1];
	params[2].ival = 2;//offCounter_c[channel_c-1];
	//params[3].ival = onTimer_c[channel_c-1];
	//params[4].ival = offTimer_c[channel_c-1];

	
	return zeroCell;
}


Cell vonplusBasic_aop_setRelinquishDefault(SedonaVM* vm, Cell* params)
{
       channel_c = params[0].ival;    
	
	float in= params[1].ival;  
	
	relinquishDefault_c= in;
	
	printf(" aop set fallback\n");


	if ((channel_to_pri[channel_c-1][0]==-1)&&(channel_to_pri[channel_c-1][1]==-1)&&
		(channel_to_pri[channel_c-1][2]==-1)&&(channel_to_pri[channel_c-1][3]==-1)&&
		(channel_to_pri[channel_c-1][4]==-1)&&(channel_to_pri[channel_c-1][5]==-1)&&
		(channel_to_pri[channel_c-1][6]==-1)&&(channel_to_pri[channel_c-1][7]==-1)&&
		(channel_to_pri[channel_c-1][8]==-1)&&(channel_to_pri[channel_c-1][9]==-1)&&
		(channel_to_pri[channel_c-1][10]==-1)&&(channel_to_pri[channel_c-1][11]==-1)&&
		(channel_to_pri[channel_c-1][12]==-1)&&(channel_to_pri[channel_c-1][13]==-1)&&
		(channel_to_pri[channel_c-1][14]==-1)&&(channel_to_pri[channel_c-1][15]==-1))		
		{ 

			channel_to_out[channel_c-1] = relinquishDefault_c; 
/*
			int fd;
			fd = open("/dev/leds0", 0);
			if (fd < 0) {
				fd = open("/dev/leds", 0);
			}
			if (fd < 0) {
				perror("open device leds");
				exit(1);
			}

			ioctl(fd, relinquishDefault_c, channel_c);
			close(fd);
*/
		}


	
	return zeroCell;
}
	


//////////////////////////////////////////////////




Cell vonplusBasic_aop_setScaleLow(SedonaVM* vm, Cell* params)
{
       channel_c = params[0].ival;    
	float scaleLow = params[1].fval;    

	scaleLow_c= scaleLow;
  
  	 return zeroCell;

}

Cell vonplusBasic_aop_setScaleHigh(SedonaVM* vm, Cell* params)
{

        channel_c= params[0].ival;    
	float scaleHigh = params[1].fval;    

	scaleHigh_c= scaleHigh;
  
  	 return zeroCell;
}




Cell vonplusBasic_aop_setClampingHighEnable(SedonaVM* vm, Cell* params)
{
	channel_c= params[0].ival;    

	clampingHighEnable_c = params[1].fval;    

//	printf("ain value: %f\n", offset_c);

  	 return zeroCell;
}

Cell vonplusBasic_aop_setClampingHigh(SedonaVM* vm, Cell* params)
{

	channel_c= params[0].ival;    

	clampingHigh_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_setClampingLowEnable(SedonaVM* vm, Cell* params)
{

	channel_c = params[0].ival;    

	clampingLowEnable_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_setClampingLow(SedonaVM* vm, Cell* params)
{
	channel_c = params[0].ival;    

	clampingLow_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_setOutputType(SedonaVM* vm, Cell* params)
{

	channel_c= params[0].ival;    

	outputType_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_setReverseOutput(SedonaVM* vm, Cell* params)
{

	channel_c = params[0].ival;    

	reverseOutput_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_setSquareRoot(SedonaVM* vm, Cell* params)
{
        channel_c = params[0].ival;    

	squareRoot_c = params[1].fval;    

  	 return zeroCell;
}

Cell vonplusBasic_aop_resetMaximumValue(SedonaVM* vm, Cell* params)
{

	channel_c = params[0].ival;    

	max_c[channel_c-1] = channel_to_out[channel_c-1];

  	 return zeroCell;
}



Cell vonplusBasic_aop_resetMinimumValue(SedonaVM* vm, Cell* params)
{

        channel_c = params[0].ival;    

	min_c[channel_c-1] = channel_to_out[channel_c-1];


	return zeroCell;
}

